#pragma once

#include "qpanel.h"


#include "qarray.h" //QBuffer
using namespace micro::utils;


#include "qfile.h"
using namespace micro::files;



#include <commdlg.h>  //dialoguri de pagesetup
#include <richedit.h>  //rich
#include <richole.h>  //ole extensions of rich
#include <ole2.h>     //ole api





namespace micro
{
namespace gui
{




class QOleCallback : public IRichEditOleCallback
{
public:

    ULONG m_cRef;			// Object Reference Count
    HWND m_hwndEdit;        // Handle of the edit control that this class
    //  is attached to.

    // Constructors and Destructor
    QOleCallback( HWND hwndEdit ) : m_cRef( 0 ), m_hwndEdit( hwndEdit ) {};
    virtual ~QOleCallback() {};

    // IUnknown Interface Members
    STDMETHODIMP 		 QueryInterface( REFIID riid, LPVOID* ppv );
    STDMETHODIMP_( ULONG ) AddRef( void );
    STDMETHODIMP_( ULONG ) Release( void );

    // IRichEditOleCallback Interface Members
    STDMETHODIMP GetNewStorage( LPSTORAGE* ppStg ); ///doc
    STDMETHODIMP GetInPlaceContext( LPOLEINPLACEFRAME* ppFrame,  LPOLEINPLACEUIWINDOW* ppDoc, LPOLEINPLACEFRAMEINFO pFrameInfo ); ///doc
    STDMETHODIMP ShowContainerUI( BOOL fShow ); ///doc

    STDMETHODIMP QueryInsertObject( LPCLSID pclsid, LPSTORAGE pStg, LONG cp );
    STDMETHODIMP DeleteObject( LPOLEOBJECT pOleObj );
    STDMETHODIMP QueryAcceptData( LPDATAOBJECT pDataObj, CLIPFORMAT* pcfFormat,	 DWORD reco, BOOL fReally, HGLOBAL hMetaPict );

    STDMETHODIMP ContextSensitiveHelp( BOOL fEnterMode );
    STDMETHODIMP GetClipboardData( CHARRANGE* pchrg, DWORD reco, LPDATAOBJECT* ppDataObject );
    STDMETHODIMP GetDragDropEffect( BOOL fDrag, DWORD grfKeyState,   LPDWORD pdwEffect );
    STDMETHODIMP GetContextMenu( WORD seltype, LPOLEOBJECT pOleObj, CHARRANGE* pchrg, HMENU* phMenu );

};

struct MYSTREAM: EDITSTREAM
{
    QBuffer* pbuff;
    int	pos;
};

class QRichEdit :	public QWindow
{
    HINSTANCE		m_hLib;      // handle to MSFTEDIT.DLL
    TEXTRANGE		m_trange;	 //TextRangeW structure, for Unicode
    CHARRANGE		m_crange;
    CHARFORMAT2		m_cformat;
    SETTEXTEX		m_stext;




    PAGESETUPDLG	m_psdPage;
    HANDLE			m_hDevMode;
    HANDLE			m_hDevNames;
    int				m_nPrinterWidth;


    QOleCallback* m_pRECallback;		// Pointer to the Callback object the   // ..edit control is using.
    //IRichEditOle* m_pRichEditOle;       // Pointer to the controls interface


public:
    QRichEdit();
    virtual ~QRichEdit( void );
    virtual bool Create( QWindow *parent, int id = 0,  UINT style = 0 ); //must respect prototype




public:


    void SetBkColor( QCOLOR col );
    void ResetBkColor();

    void SetSel( long nStartChar, long nEndChar );
    void SetSel( CHARRANGE & cr );

    void GetSel( CHARRANGE & cr );

    void SetText( QString csText, int nSTFlags, int nSTCodepage = 1200 ); //unicode

    bool SetCharFormat( DWORD dwMask,  DWORD dwEffects, LONG yHeight = 0, LPTSTR szFaceName = _T( "" ),  COLORREF crTextColor = 0,  COLORREF crBackColor = RGB( 255, 255, 255 ) );
    bool SetDefaultCharFormat( DWORD dwMask, COLORREF crTextColor, DWORD dwEffects, LPTSTR  szFaceName, LONG yHeight, COLORREF crBackColor );



    //by Sergiu
    bool SetTextColor( COLORREF crTextColor );
    bool SetTextBackground( COLORREF crBackColor );
    bool SetTextFont( LPTSTR  szFaceName );
    bool SetTextFontSize( LONG yHeight );
    bool SetTextBold() ;
    bool SetTextItalic();
    bool SetTextUnderline( );




    void LimitText( WPARAM nChars );
    void LimitTextEx( LPARAM nChars );



    void SetOptions( WORD wOp, DWORD dwFlags );
    QString GetTextRange( int ncharrMin, int ncharrMax );



    bool GetModify();
    void SetModify( bool set = true );

    bool SetOleCallback( IRichEditOleCallback *cb );
    bool GetOleInterface( IRichEditOle** ppOleInterface );
    bool InsertImage( HBITMAP bitmap );

    bool LoadFile( QFile & fis, UINT sfMode = SF_TEXT ); ///set
    bool SaveFile( QFile & fis, UINT sfMode = SF_TEXT ); //get

    bool SetRTF( QBuffer & s ); //set
    bool GetRTF( QBuffer & s ); //get





    bool PageSetup();
    bool PrintDocument( bool  silent = true );


    int GetPrinterWidth( HDC );
    HDC GetDefaultPrinterDC();
    int GetCurrentPrinterWidth();
    HDC ShowPrintDialog( HWND );




    DWORD SetEventMask( DWORD dwEventMask );

protected:


    static DWORD CALLBACK SetStreamCallback( DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, PLONG pcb );
    static DWORD CALLBACK SetStreamCallbackBE( DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, PLONG pcb );
    static DWORD CALLBACK GetStreamCallback( DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, PLONG pcb );

    static DWORD CALLBACK SetRTFCallback( DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, PLONG pcb );
    static DWORD CALLBACK GetRTFCallback( DWORD_PTR dwCookie, LPBYTE lpBuff, LONG cb, PLONG pcb );





    struct QImageIDataObject: IDataObject
    {
        STGMEDIUM m_stg;
        FORMATETC m_form;

        void SetBitmap( HBITMAP b )
        {
            FORMATETC fm =   {CF_BITMAP, nullptr, DVASPECT_CONTENT, -1, TYMED_GDI  };
            STGMEDIUM stgm = {TYMED_GDI, b, nullptr};
            SetData( &fm, &stgm, TRUE );
        }

        IOleObject *GetOleObject( IOleClientSite *pOCS, IStorage *pS )
        {
            IOleObject *pOOb = nullptr;
            OleCreateStaticFromData( this, IID_IOleObject, OLERENDER_FORMAT, &m_form, pOCS, pS, ( LPVOID* )&pOOb );
            return pOOb;
        }
        STDMETHODIMP QueryInterface( REFIID, LPVOID* )
        {
            return E_NOINTERFACE;
        }
        STDMETHODIMP_( ULONG ) AddRef()
        {
            return S_OK;
        }
        STDMETHODIMP_( ULONG ) Release()
        {
            return S_OK;
        }
        STDMETHODIMP GetData( FORMATETC*, STGMEDIUM *psm )
        {
            psm->tymed = TYMED_GDI;
            psm->hBitmap = ( HBITMAP )OleDuplicateData( m_stg.hBitmap, 2, 0 );
            psm->pUnkForRelease = nullptr;
            return S_OK;
        }
        STDMETHODIMP GetDataHere( FORMATETC*, STGMEDIUM* )
        {
            return E_NOTIMPL;
        }
        STDMETHODIMP QueryGetData( FORMATETC* )
        {
            return E_NOTIMPL;
        }
        STDMETHODIMP GetCanonicalFormatEtc( FORMATETC*, FORMATETC* )
        {
            return E_NOTIMPL;
        }
        STDMETHODIMP SetData( FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL  )
        {
            m_form = *pformatetc;
            m_stg = *pmedium;
            return S_OK;
        }
        STDMETHODIMP EnumFormatEtc( DWORD, IEnumFORMATETC** )
        {
            return E_NOTIMPL;
        }
        STDMETHODIMP DAdvise( FORMATETC*, DWORD, IAdviseSink*, DWORD* )
        {
            return E_NOTIMPL;
        }
        STDMETHODIMP DUnadvise( DWORD )
        {
            return E_NOTIMPL;
        }
        STDMETHODIMP EnumDAdvise( IEnumSTATDATA** )
        {
            return E_NOTIMPL;
        }
    };


};





class QOleInPlaceFrame : public IOleInPlaceFrame
{
private:
    ULONG m_cRef;	  			// Object reference count
    HWND  m_hwndFrame;			// Application frame window
    BOOL  m_fHelpMode;			// Context-Sensitive help mode flag

public:
    //
    // Constructors and Destructors
    //
    QOleInPlaceFrame( HWND hwndFrame = nullptr )	: m_hwndFrame( hwndFrame ), m_cRef( 0 ), m_fHelpMode( FALSE ) {}
    ~QOleInPlaceFrame();

    //
    // IUnknown Interface members
    //
    STDMETHODIMP QueryInterface( REFIID riid, LPVOID* ppv );
    STDMETHODIMP_( ULONG ) AddRef();
    STDMETHODIMP_( ULONG ) Release();

    //
    // IOleWindow Interface members
    //
    STDMETHODIMP GetWindow( HWND* pHwnd );
    STDMETHODIMP ContextSensitiveHelp( BOOL fEnterMode );

    //
    // IOleInPlaceUIWindow Interface members
    //
    STDMETHODIMP GetBorder( LPRECT prcBorder );
    STDMETHODIMP RequestBorderSpace( LPCBORDERWIDTHS pbw );
    STDMETHODIMP SetBorderSpace( LPCBORDERWIDTHS pbw );
    STDMETHODIMP SetActiveObject( LPOLEINPLACEACTIVEOBJECT pInPlaceActiveObject, LPCOLESTR szObjName );

    //
    // IOleInPlaceFrame Interface members
    //
    STDMETHODIMP InsertMenus( HMENU hmenuShared, LPOLEMENUGROUPWIDTHS pMenuWidths );
    STDMETHODIMP SetMenu( HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject );
    STDMETHODIMP RemoveMenus( HMENU hmenuShared );
    STDMETHODIMP SetStatusText( LPCOLESTR szStatusText );
    STDMETHODIMP EnableModeless( BOOL fEnable );
    STDMETHODIMP TranslateAccelerator( LPMSG pMsg, WORD wID );

    //
    // UI Helpers
    //
    void ShowUIAndTools( BOOL fShow, BOOL fMenu );
    void ReinstateUI( void );

};

//
//
//class QDocument
//{
//private:
//    HWND m_hwndFrame;                   // Handle of the frame window
//    HWND m_hwndEdit;                    // Handle of the edit control
//    LPTSTR m_pszFileName;               // Name of the current document file
//    QOleInPlaceFrame* m_pInPlaceFrame;  // Pointer to the application's
//                                        // ..IOleInPlaceFrame
//    HACCEL m_hAccelInPlace;             // Handle of the accel table for use
//                                        // ..when an object is in-place active
//    UINT m_cStorages;                   // Number of substorages we've
//                                        // ..allocated
//    QOleCallback* m_pRECallback;// Pointer to the Callback object the
//                                        // ..edit control is using.
//    LPRICHEDITOLE m_pRichEditOle;       // Pointer to the controls interface
//
//
//public:
//    //
//    // Constructors and Destructor
//    //
//	QDocument();
//    QDocument(HWND hwndFrame, HWND hwndEdit, QOleInPlaceFrame* pInPlaceFrame);
//	~QDocument();
//
//    //
//    // Initialization
//    //
//    BOOL Initialize(void);
//
//    //
//    // File I/O
//    //
//    BOOL Open(void);
//    BOOL Save(BOOL fSaveAs);
//    static DWORD CALLBACK EditStreamOut(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR *pcb);
//    static DWORD CALLBACK EditStreamIn(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb,  LONG FAR *pcb);
//
//    //
//    // Object interfaces
//    //
//    HRESULT GetNewStorage(LPSTORAGE* ppStg);
//    BOOL InsertObject();
//	HRESULT DoVerb(UINT id);
//
//    //
//    // Accessors
//    //
//    QOleInPlaceFrame* GetInPlaceFrame() { return m_pInPlaceFrame; }
//    HWND GetFrameWindow() { return m_hwndFrame; }
//    HACCEL GetInPlaceAccel() { return m_hAccelInPlace; }
//    BOOL MoveEditControl(int left, int top, int width, int height, int style);
//
//};




}
}//micro